#ifndef _SOCKETADDRESS_HPP_
#define _SOCKETADDRESS_HPP_

#include "types.hpp"
#include "jhdefs.hpp"
#include "net/SocketDefs.hpp"
#include "net/IPAddress.hpp"
#include "net/SocketAddressImpl.hpp"
#include "utils/autoptr.hpp"
using JHCPP::utils::TAutoPtr;
#include <string>

NET_NAMESPACE_BEGIN

class CSocketAddress
{
public:
	CSocketAddress();
	CSocketAddress(const CIPAddress& hostAddress, UInt16 portNumber);
	CSocketAddress(UInt16 port);
	CSocketAddress(const std::string& hostAddress, UInt16 portNumber);
	CSocketAddress(const std::string& hostAddress, const std::string& portNumber);
	explicit CSocketAddress(const std::string& hostAndPort);
	CSocketAddress(const CSocketAddress& addr);
	CSocketAddress(const struct sockaddr* addr, JH_SOCKETLEN length);
	~CSocketAddress();
	CSocketAddress& operator = (const CSocketAddress& socketAddress);

	CIPAddress host() const;
	UInt16 port() const;
	JH_SOCKETLEN length() const;
	const struct sockaddr* addr() const;
	int af() const;
	std::string toString() const;
	CIPAddress::Family family() const;

	bool operator < (const CSocketAddress& socketAddress) const;
	bool operator == (const CSocketAddress& socketAddress) const;
	bool operator != (const CSocketAddress& socketAddress) const;

	enum
	{
		MAX_ADDRESS_LENGTH = 
	#if defined(JH_HAVE_IPv6)
		sizeof(struct sockaddr_in6)
	#else
		sizeof(struct sockaddr_in)
	#endif
	};

protected:
	void init(const CIPAddress& hostAddress, UInt16 portNumber);
	void init(const std::string& hostAddress, UInt16 portNumber);
	UInt16 resolveService(const std::string& service);

private:
	typedef CSocketAddressImpl Impl;
	typedef TAutoPtr<Impl> Ptr;

	Ptr pImpl() const;
	void newIPv4();
	void newIPv4(const sockaddr_in*);
	void newIPv4(const CIPAddress& hostAddress, UInt16 portNumber);
	void newIPv6(const sockaddr_in6*);
	void newIPv6(const CIPAddress& hostAddress, UInt16 portNumber);
	void destruct();
	Ptr m_pImpl;
};

NET_NAMESPACE_END

#endif
